package framer.ui;

import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;

import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JTextField;
import javax.swing.filechooser.FileFilter;

import org.eclipse.m2m.atl.core.ATLCoreException;

import framer.Framer;


public class FramerUi extends JFrame{

	private final String BUILDING_SEARCH_SPACE_STRING = "Building Search Space";
	private final String LOADING_APPL_GOALS_STRING = "Extracting Goals from Application";
	private final String RUNNING_PLANNER_STRING = "Executing the Planner";
	private final String MAKING_DIFF_MODEL_STRING = "Calculating Model Diferences";
	private final String ADD_DIFF_TO_MODEL_STRING = "Adding diferences to original Model";
	private final String DONE_STRING = "Done";
	
	private Framer transformer;
	
	private JLabel inputModelLabel;
	private JLabel inputFrameworkLabel;
	
	private JButton chooseApplModelButton;
	private JButton chooseFrameModelButton;
	
	private JTextField applModelPath;
	private JTextField frameModelPath;
	
	private JFileChooser fileChooser;
	
	private JPanel pane;
	private JPanel runLine;
	
	private JPanel progressLine;
	private JProgressBar progress;
	private JButton save;
	
	private boolean applModelSet = false;
	private boolean frameModelSet = false;
	
	public FramerUi(Framer transformer){
		super();		
		this.transformer = transformer;
		
		JMenu menu = new JMenu("File");
		
		JMenuItem exit = new JMenuItem("Exit");
		exit.addActionListener(new ActionListener() {			
			@Override
			public void actionPerformed(ActionEvent arg0) {
				System.exit(0);				
			}
		});
		
		menu.add(exit);
		JMenuBar menubar = new JMenuBar();
		menubar.add(menu);		
		setJMenuBar(menubar);
		
		fileChooser = new JFileChooser();
		fileChooser.setFileFilter(new ModelFileFilter());
		inputModelLabel = new JLabel("Choose the input application model");
		inputFrameworkLabel = new JLabel("Choose the target framework model");
		
		chooseApplModelButton = new JButton("...");
		chooseApplModelButton.addActionListener(new ActionListener() {			
			@Override
			public void actionPerformed(ActionEvent arg0) {
				fileChooser.setSelectedFile(new File(""));
				fileChooser.setDialogTitle("Select the application model");
				if(fileChooser.showOpenDialog(FramerUi.this) == JFileChooser.APPROVE_OPTION)				
					setApplModelPath(fileChooser.getSelectedFile());				
			}
		});
		
		
		chooseFrameModelButton = new JButton("...");
		chooseFrameModelButton.addActionListener(new ActionListener() {			
			@Override
			public void actionPerformed(ActionEvent arg0) {
				fileChooser.setSelectedFile(new File(""));
				fileChooser.setDialogTitle("Select the framework model");
				if(fileChooser.showOpenDialog(FramerUi.this) == JFileChooser.APPROVE_OPTION)
					setFrameModelPath(fileChooser.getSelectedFile());
			}
		});
		
		applModelPath = new JTextField();
		applModelPath.setEditable(false);
		applModelPath.setColumns(10);
		
		frameModelPath = new JTextField();
		frameModelPath.setEditable(false);
		frameModelPath.setColumns(10);
		
		JPanel applModelLine = new JPanel(new FlowLayout());
		applModelLine.add(inputModelLabel);
		applModelLine.add(applModelPath);
		applModelLine.add(chooseApplModelButton);
		
		inputModelLabel.setLabelFor(applModelLine);		
		
		
		JPanel frameModelLine = new JPanel(new FlowLayout());
		frameModelLine.add(inputFrameworkLabel);
		frameModelLine.add(frameModelPath);
		frameModelLine.add(chooseFrameModelButton);
		
		inputFrameworkLabel.setLabelFor(frameModelLine);
		
		pane = new JPanel(new GridLayout(0,1));
		pane.add(applModelLine, BorderLayout.CENTER);
		pane.add(frameModelLine, BorderLayout.CENTER);		

		add(pane);		
		
		setVisible(true);
		setSize(320, 240);		
	}
	
	private void setApplModelPath(File file){
		System.out.println(file);
		if(file != null){
			applModelPath.setText(file.toString());
			transformer.setApplModelPath(file.toURI().toString());		
			applModelSet = true;		
			showRunButton();
		}
	}
	
	private void setFrameModelPath(File file){
		System.out.println(file);
		if(file != null){
			frameModelPath.setText(file.toString());
			transformer.setFrameworkModelPath(file.toURI().toString());			
			frameModelSet = true;
			showRunButton();
		}
	}
	
	private void showRunButton(){
		if(applModelSet && frameModelSet && (runLine == null || !runLine.isShowing())){
			runLine = new JPanel(new FlowLayout());
			JLabel runLabel = new JLabel("Execute Tranformation");
			JButton run = new JButton("Run");
			run.addActionListener(new ActionListener() {				
				@Override
				public void actionPerformed(ActionEvent e) {
					runTransformation();					
				}
			});
			runLine.add(runLabel);
			runLine.add(run);
			pane.add(runLine);
			validate();
		}		
	}
	
	private void saveModel(File file){
		if(file != null){
			String path = file.toURI().toString();			
			try {
				transformer.saveChangedModel(path);
				pane.remove(progressLine);
				validate();
			} catch (ATLCoreException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
	
	private void runTransformation(){
		pane.remove(runLine);	
		progressLine = new JPanel(new FlowLayout());
		
		save = new JButton("Save");
		save.setEnabled(false);			
		save.addActionListener(new ActionListener() {			
			@Override
			public void actionPerformed(ActionEvent arg0) {
				fileChooser.setSelectedFile(new File("ChangedModel.uml"));
				fileChooser.setDialogTitle("Save as...");
				if(fileChooser.showSaveDialog(FramerUi.this) == JFileChooser.APPROVE_OPTION)
					saveModel(fileChooser.getSelectedFile());				
			}
		});
		
		progress = new JProgressBar(0, 5);
		progress.setStringPainted(true);		

		progressLine.add(progress);
		progressLine.add(save);
		
		pane.add(progressLine);
		validate();
		
		transformer.doTransformation(this);		
	}
	
	public void progressUpdate(int phase){
		progress.setValue(phase);
		
		switch (phase) {
			case Framer.BUILDING_SEARCH_SPACE:
				progress.setString(BUILDING_SEARCH_SPACE_STRING);
				break;
			case Framer.LOADING_APPL_GOALS:
				progress.setString(LOADING_APPL_GOALS_STRING);
				break;
			case Framer.RUNNING_PLANNER:
				progress.setString(RUNNING_PLANNER_STRING);
				break;
			case Framer.MAKING_DIFF_MODEL:
				progress.setString(MAKING_DIFF_MODEL_STRING);
				break;
			case Framer.ADD_DIFF_TO_MODEL:
				progress.setString(ADD_DIFF_TO_MODEL_STRING);
				break;
			case Framer.DONE:
				progress.setString(DONE_STRING);
				save.setEnabled(true);
				break;
			default:
				break;
		}
		
		validate();
	}
	
	private class ModelFileFilter extends FileFilter{
		@Override
		public boolean accept(File file) {
			boolean isModel = false;
			
			isModel = (file.getName().indexOf(".uml") > -1) || (file.getName().indexOf(".xmi") > -1) || file.isDirectory();			
			
			return isModel;
		}

		@Override
		public String getDescription() {			
			return "*.xmi; *.uml";
		}
		
	}
}
